package com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.sap;

import com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.common.WarehousePilotService;
import com.alibaba.cirtus.ots.application.adapter.ability.model.enums.AllocateOrderStatus;
import com.alibaba.cirtus.ots.application.adapter.ability.model.enums.AllocateOrderType;
import com.alibaba.cirtus.ots.application.adapter.ability.model.enums.MnSAPStatus;
import com.alibaba.cirtus.ots.application.adapter.ability.model.request.AllocateOrderSyncRequest;
import com.alibaba.cirtus.ots.application.adapter.ability.model.request.AllocateOrderSyncScItemDetail;
import com.alibaba.cirtus.ots.application.adapter.ability.model.response.WarehouseResponse;
import com.alibaba.cirtus.ots.application.adapter.ability.utils.InfoUtil;
import com.alibaba.cirtus.ots.application.adapter.ability.utils.ResponseUtil;
import com.alibaba.citrus.ots.common.annotation.ProcessInvoker;
import com.alibaba.citrus.ots.common.util.IntegrateUtils;
import com.alibaba.citrus.ots.common.util.JsonUtil;
import com.alibaba.citrus.ots.common.util.SapAndCrmFieldDealUtils;
import com.alibaba.citrus.ots.common.util.TimeUtil;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.model.dto.BaselineGetOrganizationByIdsRequest;
import com.epoch.app.bcorder.model.dto.BaselineGetOrganizationByOutCodesRequest;
import com.epoch.app.bcorder.model.dto.WmsQueryWarehouseZoneListResponse;
import com.epoch.app.bcorder.service.BaseDataService;
import com.epoch.app.crplatformenhance.interfacedatasyncconfigquery.service.InterfaceDataSyncConfigQueryService;
import com.epoch.app.crplatformenhance.model.dto.DataCheckRequest;
import com.epoch.app.crplatformenhance.model.enums.OrderTypeEnum;
import com.epoch.app.crunifiedinventory.api.allocateorderwrite.service.AllocateOrderWriteService;
import com.epoch.app.crunifiedinventory.api.forecastwarehouse.dto.QueryWarehouseByFactoryCodeAndWarehouseCodeRequest;
import com.epoch.app.crunifiedinventory.api.forecastwarehouse.service.ForecastWarehouseService;
import com.epoch.app.crunifiedinventory.dto.response.AllocateOrderSyncResponse;
import com.epoch.app.crunifiedinventory.model.dto.WarehouseInfoDTO;
import com.epoch.app.crunifiedinventory.model.enums.FulfillmentTypeEnum;
import com.epoch.app.otsapplicationadaptersdk.materialsyncretry.model.MaterialSyncRetry;
import com.epoch.app.otsapplicationadaptersdk.materialsyncretry.service.MaterialSyncRetryService;
import com.epoch.app.otsapplicationadaptersdk.model.dto.CheckPilotByFactoryCodeAndInventoryCodeRequest;
import com.epoch.app.otsapplicationadaptersdk.model.dto.MaterialSyncRetryLoadListRequest;
import com.epoch.app.otsapplicationadaptersdk.model.dto.MessageHeaderSDO;
import com.epoch.app.otsapplicationadaptersdk.model.dto.SapRetrySaveRequest;
import com.epoch.app.otsapplicationadaptersdk.model.enums.RetryStatus;
import com.epoch.app.otsapplicationadaptersdk.model.enums.SapApiCode;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapCommDetail;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapCommResponse;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapCommSDO;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapIf004Request;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapIf008Detail;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapIf008Request;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapIf008SDO;
import com.epoch.app.otsapplicationadaptersdk.sapretrywrite.service.SapRetryWriteService;
import com.epoch.app.otsapplicationadaptersdk.sapv2.mnsapif004v2.service.MnSapIf004V2Service;
import com.epoch.app.otsapplicationadaptersdk.sapv2.mnsapif008v2.service.MnSapIf008V2Service;
import com.epoch.app.otsapplicationadaptersdk.service.OtsApplicationAdapterSdkService;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: yuhw
 * @description: sap请求平台同步调拨单创建 F-F1
 * @date: 2021年09月27日 16:58
 **/
@Component
@Primary
public class MnSapIf008V2ServiceImpl implements MnSapIf008V2Service {
    private final Log log = Log.getLogger(MnSapIf008V2ServiceImpl.class);

    @Resource
    AllocateOrderWriteService allocateOrderWriteService;
    @Resource
    private ForecastWarehouseService forecastWarehouseService;
    @Resource
    BaseDataService baseDataService;
    @Autowired
    private InterfaceDataSyncConfigQueryService interfaceDataSyncConfigQueryService;
    @Resource
    private SapRetryWriteService sapRetryWriteService;
    @Resource
    private MaterialSyncRetryService materialSyncRetryService;
    @Resource(type = MnSapIf004V2ServiceImpl.class)
    private MnSapIf004V2Service mnSapIf004V2Service;
    @Resource
    private WarehousePilotService warehousePilotService;

    private static final Integer MAX_PAGE_SIZE = 1000;
    private static final Set<String> ORG_CODE_SET = Sets.newHashSet("6140", "2827");

    @Override
    @ProcessInvoker(remark = "MnSapIf008V2Service", errorCode = "OTS-02-007-00-16-999", printLog = true)
    public MnSapCommResponse externalSyncAllocate(MnSapIf008Request mnSapIf008Request) {
        log.info("MnSapIf008ServiceImpl_externalSyncAllocate_request:{}", JSON.toJSONString(mnSapIf008Request));
        MnSapCommResponse check = check(mnSapIf008Request);
        log.info("MnSapIf008ServiceImpl_check_result:{}", JSON.toJSONString(check));
        if (check != null) {
            return check;
        }

        MnSapCommResponse response = new MnSapCommResponse();
        List<MnSapCommSDO> mnSapCommSDOS = Lists.newArrayList();
        MessageHeaderSDO messageHeaderSDO = mnSapIf008Request.getMessageHeader();
        if (Objects.isNull(messageHeaderSDO)) {
            messageHeaderSDO = IntegrateUtils.safeGetMessageHeader(MessageHeaderSDO.class);
        }
        //可能会有多个 调拨单传递
        for (MnSapIf008SDO mnSapIf008SDO : mnSapIf008Request.getData()) {
            //TODO 特殊逻辑 SAP只传工厂编码时,默认为H025 R010
            if ("H025".equals(mnSapIf008SDO.getReceiveFactoryCode()) && StringUtils.isBlank(mnSapIf008SDO.getReceiveInventoryCode())){
                mnSapIf008SDO.setReceiveInventoryCode("R010");
            }
            //发货仓若为H025，没有库存地点的时候，默认到R010去
            if ("H025".equals(mnSapIf008SDO.getDeliveryFactoryCode()) && StringUtils.isBlank(mnSapIf008SDO.getDeliveryInventoryCode())){
                mnSapIf008SDO.setDeliveryInventoryCode("R010");
            }
            AllocateOrderSyncRequest request = new AllocateOrderSyncRequest();
            //sap调拨单code
            request.setOutAllocateOrderId(mnSapIf008SDO.getOutAllocateOrderId());
            //sap调拨预报的code
            request.setOutAllocateApplyOrderId(mnSapIf008SDO.getOutAllocateApplyOrderId());
            //调拨预报单code F-F1 提报的时候已经传递了预报单code
            request.setAllocateApplyOrderCode(mnSapIf008SDO.getAllocateApplyOrderId());
            //调拨单编码 如果code不为空 且能查询到 那么先查询一遍,这个放到哪里操作呢? 这一层还是放下一层吧
            request.setCode(mnSapIf008SDO.getAllocateOrderId());
            //采购凭证 存着
            request.setTypeCard(mnSapIf008SDO.getTypeCard());
            //有就存着 不是90就是20之类的
            request.setSapChannel(mnSapIf008SDO.getSapChannel());
            //看情况需要转换 产品组 工厂 库位
            QueryWarehouseByFactoryCodeAndWarehouseCodeRequest queryRequest = new QueryWarehouseByFactoryCodeAndWarehouseCodeRequest();
            queryRequest.setWarehouseCode(mnSapIf008SDO.getReceiveInventoryCode());
            queryRequest.setFactoryCode(mnSapIf008SDO.getReceiveFactoryCode());
            log.info("MnSapIf008ServiceImpl_queryWarehouseByFactoryCodeAndWarehouseCode_receive_request:{}", JSON.toJSONString(queryRequest));
            Result<List<WarehouseInfoDTO>> listResult = forecastWarehouseService.queryWarehouseByFactoryCodeAndWarehouseCode(queryRequest);
            log.info("MnSapIf008ServiceImpl_queryWarehouseByFactoryCodeAndWarehouseCode_receive_result:{}", JSON.toJSONString(listResult));
            //一盘货，判断发货仓、收货仓是否在试点范围内
            boolean receivedWareHouseIsPilot = isInPilotScope(mnSapIf008SDO.getReceiveFactoryCode(),mnSapIf008SDO.getReceiveInventoryCode());
            String receiveAreaId = getAreaId(listResult);
            if (StringUtils.isBlank(receiveAreaId)) {
                log.info("MnSapIf008ServiceImpl_queryWarehouseByFactoryCodeAndWarehouseCode_receive_error:{}", JSON.toJSONString(mnSapIf008Request));

                return ResponseUtil.fail(mnSapIf008Request, "收货工厂和收货库位查询不到对应的收货仓");
            }
            String receiveOrgId = getOrgId(listResult);
            String orgCode = getOrgCode(receiveOrgId);
            //牛要客数据调用008的,组织编码为6140 2827的不处理直接返回成功
            if (ORG_CODE_SET.contains(orgCode)) {
                log.warn("MnSapIf008ServiceImpl.externalSyncAllocate.request:{}", JSON.toJSONString(mnSapIf008Request));
                return success(mnSapIf008Request);
            }

            try {
                //根据配置表进行数据拦截过滤
                DataCheckRequest dataCheckRequest = new DataCheckRequest();
                dataCheckRequest.setOrderType(OrderTypeEnum.ALLOCATEORDER.getCode());
                dataCheckRequest.setOrgOutCode(orgCode);
                dataCheckRequest.setVariable(SapAndCrmFieldDealUtils.toDateString(mnSapIf008SDO.getModifieroutCreateTime()));

                Result<Boolean> checkResult = interfaceDataSyncConfigQueryService.dataCheck(dataCheckRequest);
                if (checkResult != null && checkResult.getResult() != null && !checkResult.getResult()) {
                    log.info("008.interfaceDataSyncConfigQueryService 拦截 " + JSONObject.toJSONString(mnSapIf008SDO));
                    MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
                    mnSapCommSDO.setHeaderKey(mnSapIf008SDO.getHeaderKey());
                    mnSapCommSDO.setStatus(MnSAPStatus.SUCCESS.getCode());
                    mnSapCommSDO.setMessage("成功！");
                    response.setData(Lists.newArrayList(mnSapCommSDO));
                    return success(mnSapIf008Request);
                }
            } catch (Throwable e) {
                log.error("008.interfaceDataSyncConfigQueryService.Error", e);
            }

            String receiveWarehouseId = getWarehouseId(listResult);
            //先查询到逻辑仓库 逻辑库里含有工厂id 对sap传递的转换
            request.setReceiveAreaId(receiveAreaId);
            request.setReceiveWarehouseId(receiveWarehouseId);

            queryRequest.setFactoryCode(mnSapIf008SDO.getDeliveryFactoryCode());
            queryRequest.setWarehouseCode(mnSapIf008SDO.getDeliveryInventoryCode());
            log.info("MnSapIf008ServiceImpl.queryWarehouseByFactoryCodeAndWarehouseCode.ship.request:{}", JSON.toJSONString(queryRequest));
            listResult = forecastWarehouseService.queryWarehouseByFactoryCodeAndWarehouseCode(queryRequest);
            log.info("MnSapIf008ServiceImpl.queryWarehouseByFactoryCodeAndWarehouseCode.ship.result:{}", JSON.toJSONString(listResult));

            String shipAreaId = getAreaId(listResult);
            //发货仓校验
            if (StringUtils.isBlank(shipAreaId)) {
                log.info("MnSapIf008ServiceImpl.queryWarehouseByFactoryCodeAndWarehouseCode.ship.error:{}", JSON.toJSONString(mnSapIf008Request));
                return ResponseUtil.fail(mnSapIf008Request, "发货工厂和发货库位查询不到对应的发货仓");
            }
            String shipWarehouseId = getWarehouseId(listResult);
            request.setShipAreaId(shipAreaId);
            request.setShipWarehouseId(shipWarehouseId);

            if (Objects.equals(receiveAreaId, shipAreaId)) {
                log.info("MnSapIf008ServiceImpl.queryWarehouseByFactoryCodeAndWarehouseCode.same.error:{}", JSON.toJSONString(mnSapIf008Request));
                return ResponseUtil.fail(mnSapIf008Request, "发货仓和收货仓不能是同一个");
            }
            //产品组 不知道要不要转换 现在就是给什么存什么
            request.setProductGroup(mnSapIf008SDO.getProductGroupCode());
            //把这个塞到我们的创建者里 需不要存 另说
            request.setCreator(mnSapIf008SDO.getOutCreator());
            //这个字段原来是想存创建者的 也存着
            request.setFounder(mnSapIf008SDO.getOutCreator());
            //更改人 也存着
            request.setLastUpdateUser(mnSapIf008SDO.getModifier());
            //时间也存着 是否时分秒之后再改
            request.setCreateTime(TimeUtil.parseSimpleDateFormat(mnSapIf008SDO.getOutCreateTime()));
            // 运输方式可能要转换 理论上我们应该存库里整数 这个再说
            request.setShipMethod(StringUtils.isNotBlank(mnSapIf008SDO.getShipType()) ?
                    Integer.parseInt(mnSapIf008SDO.getShipType()) : null);
            if (StringUtils.isNotBlank(mnSapIf008SDO.getRemark())) {
                if (mnSapIf008SDO.getRemark().length() > 200){
                    request.setRemark(mnSapIf008SDO.getRemark().substring(0, 200));
                }else {
                    request.setRemark(mnSapIf008SDO.getRemark());
                }
            }
            request.setReturnOrder("1".equals(mnSapIf008SDO.getReturnGoods()));
            //觉得新来一个字段用来存额外的features 想把创建信息保存下,如果返回时有需要返回去 算了 后面有需要再改吧
            request.setFeatures(mnSapIf008SDO.getFeatures());
            //发货工厂转成组织
            //获取预调拨单里的提报组织 因为是F-F1 必有提报所以直接去查我们的库 它也没传
            //产品说这个场景不需要
            //因为组织从预报单里取 所以用不着调用接口了.
            BaselineGetOrganizationByOutCodesRequest baselineGetOrganizationByOutCodesRequest = new BaselineGetOrganizationByOutCodesRequest();
            baselineGetOrganizationByOutCodesRequest.setOutCodes(Lists.newArrayList("222"));
            baselineGetOrganizationByOutCodesRequest.setStatus(1);
            //因为是F-F1 类型确定了.  但是也可能是跨公司借货调拨, 所以 type在更新时不要去传递.
            request.setType(AllocateOrderType.PLAN.getType());
            request.setStatus(AllocateOrderStatus.Shipment_Processing.getValue());
            //单据日期
            request.setDocDate(TimeUtil.parseSimpleDateFormat(mnSapIf008SDO.getOutCreateTime()));
            request.setExt(mnSapIf008SDO.getExt());
//            request.setFeatures(mnSapIf008SDO.getFeatures());
            List<MnSapIf008Detail> mnSapIf008Details = mnSapIf008SDO.getItems();
            List<AllocateOrderSyncScItemDetail> details = Lists.newArrayList();
//            List<MnSapCommDetail> mnSapCommDetails = Lists.newArrayList();
            MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
            if (CollectionUtils.isNotEmpty(mnSapIf008Details)) {
                for (MnSapIf008Detail data : mnSapIf008Details) {
                    AllocateOrderSyncScItemDetail detail = new AllocateOrderSyncScItemDetail();
                    detail.setLineNo(data.getAllocateOrderLineId());
                    //sap的调拨单行号 行号前去0
                    detail.setOutAllocateOrderLineId(InfoUtil.deleteZeroPrefix(data.getOutAllocateOrderLineId()));
                    //sap的调拨预报的行号
                    detail.setOutAllocateApplyOrderLineId(data.getOutAllocateApplyOrderLineId());
                    //调拨预报单行号
                    detail.setAllocateApplyOrderLineId(data.getAllocateApplyOrderLineId());
                    //调拨单行号
                    detail.setAllocateOrderLineId(data.getAllocateOrderLineId());
                    //货品code 理论两边应该一样
                    detail.setScItemCode(subStringScItmCode(data.getScItemId()));
                    //数量
                    detail.setQuantity(data.getQuantity());
                    //确认的数量 sap传递的值
                    //退单做特殊处理逻辑, 确认数量=订单数量；
                    if (request.getReturnOrder()) {
                        detail.setConfirmQuantity(data.getQuantity());
                    } else {
                        detail.setConfirmQuantity(data.getConfirmQuantity());
                    }
                    //单价/ 单位净价
                    detail.setUnitPrice(data.getPrice());
                    //单价
                    detail.setPrice(data.getPrice());
                    //单位
                    detail.setUnit(data.getUnit());
//                    detail.setProductGroup()
                    //生产日期 直接转date
                    //2022/03/27  00000000 或者为空 生产日期给默认值
                    if (StringUtils.isBlank(data.getExpectedProduceDate()) || "00000000".equals(data.getExpectedProduceDate())) {
//                        detail.setExpectedProduceDate(TimeUtil.parseSimpleDateFormat("20000101"));
                    } else {
                        detail.setExpectedProduceDate(TimeUtil.parseSimpleDateFormat(data.getExpectedProduceDate()));
                    }
                    //含税价
                    detail.setSubTotalAmount(data.getSubTotalAmt());
                    //是否关闭 创建时应该都是开着
                    detail.setClosed("1".equals(data.getIsClosed()) ? Boolean.TRUE : Boolean.FALSE);
                    //2022.05.12 去掉设置为0的逻辑
//                    if (detail.getClosed()) {
//                        detail.setQuantity("0");
//                        detail.setConfirmQuantity("0");
//                    }
                    //交货日期
                    if (StringUtils.isNotBlank(data.getExpectedDeliveryDate())) {
                        detail.setExpectedDeliveryDate(TimeUtil.parseSimpleDateFormat(data.getExpectedDeliveryDate()));
                    }
                    detail.setFeatures(data.getFeatures());
                    //确认日期问题
                    if (StringUtils.isNotBlank(data.getExt())) {
                        detail.setConfirmTime(TimeUtil.parseSimpleDateFormat(data.getExt()));
                    }
                    details.add(detail);
                }
            }
            request.setAllocateOrderScItemDetails(details);
            com.epoch.app.crunifiedinventory.dto.request.AllocateOrderSyncRequest allocateOrderSyncRequest =
                    JsonUtil.convert(request,
                            com.epoch.app.crunifiedinventory.dto.request.AllocateOrderSyncRequest.class);
            log.info("MnSapIf008ServiceImpl_passiveSync_request:{}", JSON.toJSONString(allocateOrderSyncRequest));
            //一盘货，判断发货仓、收货仓是否在试点范围内
            boolean deliveryWareHouseIsPilot = isInPilotScope(mnSapIf008SDO.getDeliveryFactoryCode(),mnSapIf008SDO.getDeliveryInventoryCode());
             if (receivedWareHouseIsPilot || deliveryWareHouseIsPilot) {
                 //只要发货仓、收货仓有一个在试点范围内，则是自动履约
                 allocateOrderSyncRequest.setAutoFulfillment(Boolean.TRUE);
             }
             if (receivedWareHouseIsPilot && deliveryWareHouseIsPilot) {
                 //收货仓、发货仓都在试点范围内 收发货仓的物理仓一样 是虚拟移库
                 if (Objects.equals(shipWarehouseId,receiveWarehouseId)){
                     allocateOrderSyncRequest.setFulfillmentTypeCode(FulfillmentTypeEnum.VIRTUAL_TRANSFER.getValue().toString());
                 }else {
                     allocateOrderSyncRequest.setFulfillmentTypeCode(FulfillmentTypeEnum.PILOT2PILOT.getValue().toString());
                 }
             } else if (receivedWareHouseIsPilot && !deliveryWareHouseIsPilot) {
                 //收货仓在试点范围内, 发货仓不在试点范围内
                 if (Boolean.TRUE.equals(request.getReturnOrder())){
                     allocateOrderSyncRequest.setFulfillmentTypeCode(FulfillmentTypeEnum.PILOT2CURRENT.getValue().toString());
                 }else {
                     allocateOrderSyncRequest.setFulfillmentTypeCode(FulfillmentTypeEnum.CURRENT2PILOT.getValue().toString());
                 }
             } else if (!receivedWareHouseIsPilot && deliveryWareHouseIsPilot) {
                 //收货仓不在试点范围内, 发货仓在试点范围内
                 if (Boolean.TRUE.equals(request.getReturnOrder())){
                     allocateOrderSyncRequest.setFulfillmentTypeCode(FulfillmentTypeEnum.CURRENT2PILOT.getValue().toString());
                 }else {
                     allocateOrderSyncRequest.setFulfillmentTypeCode(FulfillmentTypeEnum.PILOT2CURRENT.getValue().toString());
                 }
             }else if (!receivedWareHouseIsPilot && !deliveryWareHouseIsPilot){
                 allocateOrderSyncRequest.setFulfillmentTypeCode(FulfillmentTypeEnum.CURRENT2CURRENT.getValue().toString());
             }
             log.info(" sap008 passiveSync param :{}", JSON.toJSONString(allocateOrderSyncRequest));
            Result<AllocateOrderSyncResponse> allocateOrderSyncResponseResult;
             if (Boolean.TRUE.equals(deliveryWareHouseIsPilot) || Boolean.TRUE.equals(receivedWareHouseIsPilot)){
                 allocateOrderSyncResponseResult = allocateOrderWriteService.syncAllocateOrder(allocateOrderSyncRequest);
             }else {
                 allocateOrderSyncResponseResult = allocateOrderWriteService.passiveSync(allocateOrderSyncRequest);
             }
            log.info("MnSapIf008ServiceImpl_passiveSync_request:{}", JSON.toJSONString(allocateOrderSyncResponseResult));

            String code = null;
            if (allocateOrderSyncResponseResult.getResult() != null) {
                code = allocateOrderSyncResponseResult.getResult().getCode();
            }

            mnSapCommSDO.setHeaderKey(mnSapIf008SDO.getHeaderKey());
            mnSapCommSDO.setExtId(code);

            if (StringUtils.isNotBlank(code) && code.startsWith("STO")) {
                mnSapCommSDO.setMessage(MnSAPStatus.SUCCESS.getMsg());
                mnSapCommSDO.setStatus(MnSAPStatus.SUCCESS.getCode());
                retry(request.getOutAllocateOrderId(),true);
            } else {
                mnSapCommSDO.setMessage(code);
                mnSapCommSDO.setStatus(MnSAPStatus.ERROR.getCode());
                mnSapCommSDO.setExtId(null);
                saveSapRetry(mnSapIf008Request,mnSapIf008SDO,code);
            }
            List<MnSapCommDetail> mnSapCommDetails = Lists.newArrayList();
            if (CollectionUtils.isNotEmpty(mnSapIf008SDO.getItems())) {
                String finalCode = code;
                mnSapCommDetails = mnSapIf008SDO.getItems().stream().map(m -> {
                    MnSapCommDetail mnSapCommDetail = new MnSapCommDetail();
                    mnSapCommDetail.setItemKey(m.getItem_key());
                    if (StringUtils.isNotBlank(finalCode) && finalCode.startsWith("STO")) {
                        mnSapCommDetail.setStatus(MnSAPStatus.SUCCESS.getCode());
                        mnSapCommDetail.setMessage(MnSAPStatus.SUCCESS.getMsg());
                    } else {
                        mnSapCommDetail.setStatus(MnSAPStatus.ERROR.getCode());
                        mnSapCommDetail.setMessage(finalCode);
                    }
                    return mnSapCommDetail;
                }).collect(Collectors.toList());
            }

            mnSapCommSDO.setItem(mnSapCommDetails);
            mnSapCommSDOS.add(mnSapCommSDO);
        }
        response.setData(mnSapCommSDOS);
        if (Objects.nonNull(messageHeaderSDO)) {
            response.setInterfacePath(messageHeaderSDO.getInterfacePath());
            response.setMessageId(messageHeaderSDO.getMessageId());
        }
        return response;
    }

    /**
     * 牛要客数据调用008的,组织编码为6140 2827的不改动
     *
     * @param request
     * @return
     */
    public static MnSapCommResponse success(MnSapIf008Request request) {
        MnSapCommResponse response = new MnSapCommResponse();
        MessageHeaderSDO messageHeaderSDO = request.getMessageHeader();
        if (CollectionUtils.isNotEmpty(request.getData())) {
            List<MnSapCommSDO> mnSapCommSDOS = Lists.newArrayList();
            for (MnSapIf008SDO mnSapIf008SDO : request.getData()) {
                MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
                mnSapCommSDO.setHeaderKey(mnSapIf008SDO.getHeaderKey());
                mnSapCommSDO.setExtId(null);
                mnSapCommSDO.setMessage(MnSAPStatus.SUCCESS.getMsg());
                mnSapCommSDO.setStatus(MnSAPStatus.SUCCESS.getCode());
                List<MnSapCommDetail> mnSapCommDetails = Lists.newArrayList();
                if (CollectionUtils.isNotEmpty(mnSapIf008SDO.getItems())) {
                    mnSapCommDetails = mnSapIf008SDO.getItems().stream().map(m -> {
                        MnSapCommDetail mnSapCommDetail = new MnSapCommDetail();
                        mnSapCommDetail.setItemKey(m.getItem_key());
                        mnSapCommDetail.setStatus(MnSAPStatus.SUCCESS.getCode());
                        mnSapCommDetail.setMessage(MnSAPStatus.SUCCESS.getMsg());
                        return mnSapCommDetail;
                    }).collect(Collectors.toList());
                    mnSapCommSDO.setItem(mnSapCommDetails);
                }
                mnSapCommSDOS.add(mnSapCommSDO);
            }
            response.setData(mnSapCommSDOS);
        }
        if (Objects.nonNull(messageHeaderSDO)) {
            response.setInterfacePath(messageHeaderSDO.getInterfacePath());
            response.setMessageId(messageHeaderSDO.getMessageId());
        }
        return response;
    }

    /**
     * 根据map来获取
     *
     * @param map
     * @return
     */
    public static String getCode(Map map) {
        JSONObject obj = JSONObject.parseObject(JSONObject.toJSONString(map));
        if (obj != null) {
            obj = obj.getJSONObject("result");
            if (obj != null) {
                obj = obj.getJSONObject("result");
                if (obj != null) {
                    return obj.getString("code");
                }
            }
        }
        return null;
    }


    public static String getWarehouseId(WmsQueryWarehouseZoneListResponse response) {
        if (response != null && CollectionUtils.isNotEmpty(response.getResult())) {
            WarehouseResponse warehouseResponse = JsonUtil.convert(response.getResult().get(0),
                    WarehouseResponse.class);
            return warehouseResponse.getWarehouseId();
        }
        return null;
    }

    public static String getAreaId(WmsQueryWarehouseZoneListResponse response) {
        if (response != null && CollectionUtils.isNotEmpty(response.getResult())) {
            WarehouseResponse warehouseResponse = JsonUtil.convert(response.getResult().get(0),
                    WarehouseResponse.class);
            return warehouseResponse.getId();
        }
        return null;
    }

    public static String getWarehouseId(Result<List<WarehouseInfoDTO>> result) {
        if (result != null && CollectionUtils.isNotEmpty(result.getResult())) {
            WarehouseInfoDTO warehouseInfoDTO = result.getResult().get(0);
            return warehouseInfoDTO.getWarehouseId();
        }
        return null;
    }

    public static String getAreaId(Result<List<WarehouseInfoDTO>> result) {
        if (result != null && CollectionUtils.isNotEmpty(result.getResult())) {
            WarehouseInfoDTO warehouseInfoDTO = result.getResult().get(0);
            return warehouseInfoDTO.getId();
        }
        return null;
    }

    public static String getOrgId(Result<List<WarehouseInfoDTO>> result) {
        if (result != null && CollectionUtils.isNotEmpty(result.getResult())) {
            WarehouseInfoDTO warehouseInfoDTO = result.getResult().get(0);
            return warehouseInfoDTO.getSaleOrgId();
        }
        return null;
    }

    public String getOrgCode(String orgId) {
        //发货收货仓的组织id name
        BaselineGetOrganizationByIdsRequest r = new BaselineGetOrganizationByIdsRequest();
        if (StringUtils.isNotBlank(orgId)) {
            r.setIds(Lists.newArrayList(orgId));
            Object obj = baseDataService.baselineGetOrganizationByIds(r);
            JSONObject o = JSONObject.parseObject(JSONObject.toJSONString(obj));
            if (o != null) {
                JSONArray array = o.getJSONArray("result");
                if (array != null && array.size() > 0) {
                    JSONObject j = array.getJSONObject(0).getJSONObject("organizationSDO");
                    if (j != null) {
                        return j.getString("code");
                    }
                }
            }
        }
        return null;
    }


    public static MnSapCommResponse check(MnSapIf008Request request) {
        if (CollectionUtils.isEmpty(request.getData())) {
            String dataStr = IntegrateUtils.safeGetDataJson();
            if (StringUtils.isEmpty(dataStr)) {
                return ResponseUtil.fail(request, "传递的调拨单参数列表为空");
            }
            List<MnSapIf008SDO> mnSapIf008SDOS = JSON.parseArray(dataStr, MnSapIf008SDO.class);
            if (CollectionUtils.isEmpty(mnSapIf008SDOS)) {
                return ResponseUtil.fail(request, "传递的调拨单参数列表为空");
            }
            request.setData(mnSapIf008SDOS);
        }
        String msg = null;
        for (MnSapIf008SDO sdo : request.getData()) {
            if (StringUtils.isBlank(sdo.getOutAllocateOrderId())) {
                msg = "outAllocateOrderId不能为空";
                break;
            }
            if (StringUtils.isBlank(sdo.getReceiveFactoryCode())) {
                msg = "receiveFactoryCode 不能为空";
                break;
            }
//            if (StringUtils.isBlank(sdo.getReceiveInventoryCode())){
//                msg = "receiveInventoryCode 不能为空";
//            }
            if (StringUtils.isBlank(sdo.getDeliveryFactoryCode())) {
                msg = "deliveryFactoryCode 不能为空";
                break;
            }
//            if (StringUtils.isBlank(sdo.getDeliveryInventoryCode())){
////                msg = "deliveryInventoryCode 不能为空";
////                break;
//                sdo.setDeliveryInventoryCode("DEFAULT");
//            }
            if (CollectionUtils.isEmpty(sdo.getItems())) {
                msg = "items 不能为空";
                break;
            }
            //修改时间 格式为20220307111350.3513180 前面年月日时分秒 后面是 0.3513180
            if (StringUtils.isBlank(sdo.getExt())) {
                msg = "ext修改时间不能为空";
                break;
            } else {
                String[] split = sdo.getExt().split("\\.");
                if (split.length != 2) {
                    msg = "ext修改时间 格式错误";
                    break;
                }
            }


            for (MnSapIf008Detail detail : sdo.getItems()) {
                if (StringUtils.isBlank(detail.getOutAllocateOrderLineId())) {
                    return ResponseUtil.fail(request, "outAllocateOrderLineId 不能为空");
                }
                if (StringUtils.isBlank(detail.getScItemId())) {
                    return ResponseUtil.fail(request, "scItemId 不能为空");
                }
                if (StringUtils.isBlank(detail.getQuantity())) {
                    return ResponseUtil.fail(request, "quantity 不能为空");
                }
//                if (StringUtils.isBlank(detail.getConfirmQuantity())) {
//                    return ResponseUtil.fail(request, "confirmQuantity 不能为空");
//                }
//                if (StringUtils.isBlank(detail.getPrice())) {
//                    return ResponseUtil.fail(request, "price 不能为空");
//                }
                if (StringUtils.isBlank(detail.getUnit())) {
                    return ResponseUtil.fail(request, "unit 不能为空");
                }
                if (StringUtils.isBlank(detail.getIsClosed())) {
                    return ResponseUtil.fail(request, "isClosed 不能为空");
                }
                if (StringUtils.isNotBlank(detail.getIsClosed())) {
                    if (!"1".equals(detail.getIsClosed())) {
                        BigDecimal decimal = new BigDecimal(detail.getQuantity().trim());
                        if (decimal.intValue() <= 0) {
                            return ResponseUtil.fail(request, "非关闭情况下数量不能小于等于0");
                        }
                    }
                }
            }
            //判断是否有重复的物流
            List<String> collect = sdo.getItems().stream().map(x -> {
//                return SapAndCrmFieldDealUtils.generateIdField(x.getScItemId());
                return subStringScItmCode(x.getScItemId());
            }).distinct().collect(Collectors.toList());
            if (CollectionUtils.isEmpty(collect)) {
                return ResponseUtil.fail(request, "有效items不能为空");
            }
            //物料 去0后不能重复 放在后面校验
//            if (collect.size() < sdo.getItems().size()) {
//                return ResponseUtil.fail(request, "物料编码不能重复");
//            }
        }
        if (msg != null) {
            return ResponseUtil.fail(request, msg);
        }
        return null;
    }

    /**
     * 截取scItemCode 固定长度为12
     *
     * @param str
     * @return
     */
    public static String subStringScItmCode(String str) {
        if (StringUtils.isBlank(str)) {
            return null;
        }
        if (str.length() > 12) {
            return str.substring(str.length() - 12);
        }
        return str;
    }

    /**
     * 保存sap重试记录
     *
     */
    public void saveSapRetry(MnSapIf008Request request,MnSapIf008SDO sdo, String code){
        try{
            if (request == null || (StringUtils.isNotBlank(code) && code.startsWith("STO"))){
                return;
            }
            SapRetrySaveRequest sapRetrySaveRequest = new SapRetrySaveRequest();
            String requestJson = JSON.toJSONString(request);
            sapRetrySaveRequest.setParam(requestJson);
            sapRetrySaveRequest.setMsg(code);
            sapRetrySaveRequest.setMessageId(request.getMessageHeader().getMessageId());
            //请求时间戳
            sapRetrySaveRequest.setRequestTime(sdo.getExt());
            sapRetrySaveRequest.setApiCode(SapApiCode.SAP008.getValue());
            sapRetrySaveRequest.setOutKey(sdo.getOutAllocateOrderId());
            sapRetrySaveRequest.setStatus(RetryStatus.FAIL.getValue());
            sapRetryWriteService.save(sapRetrySaveRequest);
        }catch (Throwable e){
            log.error("sapRetrySaveError",e);
        }
    }

    private void retry(String outAllocateOrderId,boolean canRetry){
        if (!canRetry){
            return;
        }
        MaterialSyncRetryLoadListRequest materialSyncRetryLoadListRequest = new MaterialSyncRetryLoadListRequest();
        materialSyncRetryLoadListRequest.setOutOrderId(outAllocateOrderId);
        materialSyncRetryLoadListRequest.setStatus(0);
        materialSyncRetryLoadListRequest.setLimit(MAX_PAGE_SIZE);
        Result<List<MaterialSyncRetry>> listResult = materialSyncRetryService.loadList(materialSyncRetryLoadListRequest);
        if (listResult != null && CollectionUtils.isNotEmpty(listResult.getResult())){
            for (MaterialSyncRetry materialSyncRetry : listResult.getResult()) {
                try {
                    MnSapIf004Request mnSapIf004Request = JSON.parseObject(materialSyncRetry.getRequestParams(),MnSapIf004Request.class);
                    mnSapIf004V2Service.externalSyncMaterial(mnSapIf004Request);
                }catch (Throwable e){
                    log.error("MnSapIf008V2ServiceImpl_retry",e);
                    log.error("MnSapIf008V2ServiceImpl_retry,request:{},004:{}",JSON.toJSONString(outAllocateOrderId),JSON.toJSONString(listResult.getResult()));
                }
                continue;
            }
        }
    }
    /**
     * 根据工厂编码 + 库存地点
     * @param factoryCode
     * @param warehouseCode
     * @return
     */
    public boolean isInPilotScope(String factoryCode,String warehouseCode){
        return warehousePilotService.isInPilotScope(factoryCode, warehouseCode);
    }
}
